package com.smedi.ismedi.personnel.core.port.adapter.restful;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.smedi.ismedi.authority.starter.response.AuthorityAccessResponse;
import com.smedi.ismedi.authority.starter.response.InternalAssignmentInfoResponse;
import com.smedi.ismedi.authority.starter.util.AuthorityUtil;
import com.smedi.ismedi.authoritymanagement.api.dto.request.DataPermissionScopeRequest;
import com.smedi.ismedi.constructionproject.api.dto.response.ProjectBasicResponse;
import com.smedi.ismedi.database.starter.annotation.SkipSqlPermission;
import com.smedi.ismedi.database.starter.interceptor.permission.SqlItemEnum;
import com.smedi.ismedi.organization.api.dto.response.HrOrganizationResponse;
import com.smedi.ismedi.organization.api.dto.response.ProjectOrganizationResponse;
import com.smedi.ismedi.personnel.api.dto.request.*;
import com.smedi.ismedi.personnel.api.dto.response.*;
import com.smedi.ismedi.personnel.api.dto.response.resp.OrganizationAssignmentResp;
import com.smedi.ismedi.personnel.api.dto.response.resp.PersonDetailResp;
import com.smedi.ismedi.personnel.api.dto.response.resp.PersonResp;
import com.smedi.ismedi.personnel.api.feign.RemotePersonCoreFeignApi;
import com.smedi.ismedi.personnel.core.application.command.*;
import com.smedi.ismedi.personnel.core.application.query.PersonQueryService;
import com.smedi.ismedi.personnel.core.application.query.PersonSyncQueryService;
import com.smedi.ismedi.personnel.core.application.query.SubOrganizationSyncQueryService;
import com.smedi.ismedi.personnel.core.application.query.vo.PersonDetailVo;
import com.smedi.ismedi.personnel.core.application.query.vo.PersonInfoVo;
import com.smedi.ismedi.personnel.core.application.service.ImisSyncApplicationService;
import com.smedi.ismedi.personnel.core.application.service.PersonApplicationService;
import com.smedi.ismedi.personnel.core.domain.aggregatemodel.Assignment;
import com.smedi.ismedi.personnel.core.domain.aggregatemodel.Person;
import com.smedi.ismedi.personnel.core.domain.aggregatemodel.PersonSyncFromImis;
import com.smedi.ismedi.personnel.core.domain.aggregatemodel.model.OrganizationAssignment;
import com.smedi.ismedi.personnel.core.domain.aggregatemodel.model.SimplePerson;
import com.smedi.ismedi.personnel.core.infrastructure.constant.CustomError;
import com.smedi.ismedi.personnel.core.port.adapter.convert.AdapterConverter;
import com.smedi.ismedi.personnel.core.port.adapter.service.AuthorityAccessRemoteApiService;
import com.smedi.ismedi.personnel.core.port.adapter.service.ConstructionProjectRemoteApiService;
import com.smedi.ismedi.personnel.core.port.adapter.service.OrganizationRemoteApiService;
import com.smedi.ismedi.web.starter.common.PaginationData;
import com.smedi.ismedi.web.starter.common.ResponseData;
import com.smedi.ismedi.web.starter.exception.BasicError;
import com.smedi.ismedi.web.starter.exception.LogicException;
import com.smedi.ismedi.web.starter.util.DozerUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: xulinjun
 * @Date: 2021-6-8 13:31
 */
@Slf4j
@RestController
@AllArgsConstructor
public class PersonCoreController implements RemotePersonCoreFeignApi {
    private final DozerUtil dozerUtil;
    private final AuthorityUtil authorityUtil;

    private final PersonApplicationService personApplicationService;
    private final PersonQueryService personQueryService;
    private final PersonSyncQueryService personSyncQueryService;
    private final ImisSyncApplicationService imisSyncApplicationService;
    private final ConstructionProjectRemoteApiService constructionProjectRemoteApiService;
    private final OrganizationRemoteApiService organizationRemoteApiService;
    private final SubOrganizationSyncQueryService subOrganizationSyncQueryService;
    private final AuthorityAccessRemoteApiService authorityAccessRemoteApiService;


    private final AdapterConverter adapterConverter;

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<PersonResponse> postSaveExternalPerson(ExternalPersonRequest externalPersonRequest) {
        PersonBasicCommand personBasicCommand = dozerUtil.convertor(externalPersonRequest, PersonBasicCommand.class);
        ProjectAssigmentCommand projectAssigmentCommand = dozerUtil.convertor(externalPersonRequest, ProjectAssigmentCommand.class);
        personBasicCommand.setProjectAssigmentCommand(projectAssigmentCommand);

        Person person = personApplicationService.saveExternalPerson(personBasicCommand);
        return new ResponseData<PersonResponse>().success(dozerUtil.convertor(person, PersonResponse.class));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<PersonResponse> postSaveInternalPerson(InternalPersonRequest internalPersonRequest) {
        PersonBasicCommand personBasicCommand = dozerUtil.convertor(internalPersonRequest, PersonBasicCommand.class);
        PersonAssigmentCommand personAssigmentCommand = dozerUtil.convertor(internalPersonRequest, PersonAssigmentCommand.class);
        personBasicCommand.setPersonAssigmentCommand(personAssigmentCommand);

        Person person = personApplicationService.saveInternalPerson(personBasicCommand);
        return new ResponseData<PersonResponse>().success(dozerUtil.convertor(person, PersonResponse.class));
    }

    @Override
    public ResponseData<Boolean> editPerson(PersonEditRequest personEditRequest) {
        PersonEditCommand personEditCommand = adapterConverter.personEditRequestToPersonEditCommand(personEditRequest);
        personApplicationService.editPerson(personEditCommand);
        return new ResponseData<>().success(true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<PaginationData<InternalPersonAssignmentResponse>> getQueryInternalPersonInfoPagination(Long offset, Long pageSize, Long hrOrganizationId, String lastName, String userName, String employeeNum, boolean containHrOrganizationChildren) {
        IPage pagination;
        if (containHrOrganizationChildren) {
            pagination = personQueryService.getPersonPaginationByInternalAssignmentContainsChildren(offset, pageSize, hrOrganizationId, lastName, userName, employeeNum);
        } else {
            pagination = personQueryService.getPersonPaginationByInternalAssignment(offset, pageSize, hrOrganizationId, lastName, userName, employeeNum);
        }
        pagination.setRecords(dozerUtil.convertor(pagination.getRecords(), InternalPersonAssignmentResponse.class));
        PaginationData<InternalPersonAssignmentResponse> paginationData = dozerUtil.convertor(pagination, PaginationData.class);
        return new ResponseData<PaginationData>().success(paginationData);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<PaginationData> getQueryInternalPersonPickupPagination(Long offset, Long pageSize, String lastName, String employeeNum) {
        IPage pagination = personQueryService.getPersonPaginationPickUp(offset, pageSize, lastName, employeeNum);
        pagination.setRecords(dozerUtil.convertor(pagination.getRecords(), PersonSimpleResponse.class));

        PaginationData PaginationData = dozerUtil.convertor(pagination, PaginationData.class);
        return new ResponseData<PaginationData>().success(PaginationData);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<PersonResponse> getQueryInternalPersonInfo(Long personId, Long hrOrganizationId) {
        PersonInfoVo personInfoVo = personQueryService.getPersonInfo(personId, hrOrganizationId);
        return new ResponseData<PersonResponse>().success(dozerUtil.convertor(personInfoVo, PersonResponse.class));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<PaginationData> getQueryPersonSyncFromImisPagination(Long offset, Long pageSize, String lastName, String employeeNum, String hrJob, Long subOrganizationId) {
        IPage pagination = personSyncQueryService.selectPersonSyncVoPagination(offset, pageSize, lastName, employeeNum, hrJob, subOrganizationId);
        pagination.setRecords(dozerUtil.convertor(pagination.getRecords(), PersonSyncFromImisPaginationResponse.class));

        PaginationData PaginationData = dozerUtil.convertor(pagination, PaginationData.class);
        return new ResponseData<PaginationData>().success(PaginationData);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<List<SubOrganizationSyncFromImisResponse>> getQuerySubOrganizationSyncListFromImis() {
        return new ResponseData<List<SubOrganizationSyncFromImisResponse>>().success(dozerUtil.convertor(subOrganizationSyncQueryService.queryList(), SubOrganizationSyncFromImisResponse.class));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<List<PersonSyncFromImisResponse>> postBatchSavePersonSyncFromImis(Long[] referencePersonIds, Long hrOrganizationId) {
        // 人员id去重
        Set<Long> set = new HashSet<>();
        for (Long referencePersonId : referencePersonIds) {
            set.add(referencePersonId);
        }
        List<PersonSyncFromImis> list = imisSyncApplicationService.batchSavePerson(set, hrOrganizationId);
        List<PersonSyncFromImisResponse> response = dozerUtil.convertor(list, PersonSyncFromImisResponse.class);

        return new ResponseData<List<PersonSyncFromImisResponse>>().success(response);
    }

    @Override
    public ResponseData<List<PersonSyncFromImisResponse>> postBatchSavePersonSyncFromImisToProjectOrganization(Long[] referencePersonIds, Long projectId, Long projectOrganizationId) {
        // 人员id去重
        Set<Long> set = new HashSet<>();
        for (Long referencePersonId : referencePersonIds) {
            set.add(referencePersonId);
        }
        List<PersonSyncFromImis> list = imisSyncApplicationService.batchSavePersonToProjectOrganization(set, projectId, projectOrganizationId);
        List<PersonSyncFromImisResponse> response = dozerUtil.convertor(list, PersonSyncFromImisResponse.class);

        return new ResponseData<List<PersonSyncFromImisResponse>>().success(response);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<List<Long>> getQueryPersonIdsByLastNameAndUserNameAndEmployeeNumAndMobile(String lastName, String userName, String employeeNum, String mobile) {
        List<Long> personIds = personQueryService.getPersonIdsByLastNameAndUserNameAndEmployeeNumAndMobile(lastName, userName, employeeNum, mobile);
        return new ResponseData<List<Long>>().success(personIds);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<List<PersonSimpleResponse>> getQueryPersonSimpleList(List<Long> personIds) {
        List<PersonInfoVo> list = personQueryService.getPersonInfoByPersonIds(personIds);
        List<PersonSimpleResponse> responses = dozerUtil.convertor(list, PersonSimpleResponse.class);

        return new ResponseData<List<PersonSimpleResponse>>().success(responses);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<PaginationData> getQueryPersonManagementPagination(Long offset, Long pageSize, String lastName, String userName, String employeeNum, String personType, String status, Boolean internal, Long nonOrganizationId, boolean nonAllHrOrganization) {
        IPage pagination = personQueryService.getPersonManagementPagination(offset, pageSize, lastName, userName, employeeNum, personType, status, internal, nonOrganizationId, nonAllHrOrganization);
        PaginationData PaginationData = dozerUtil.convertor(pagination, PaginationData.class);
        return new ResponseData<PaginationData>().success(PaginationData);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<PersonResponse> getQueryPersonDetailInfo(Long personId) {
        PersonInfoVo personInfoVo = personQueryService.getPersonDetailInfo(personId);
        PersonResponse personResponse = dozerUtil.convertor(personInfoVo, PersonResponse.class);

        // 获取项目分配信息
        personResponse.setProjectAssignments(dozerUtil.convertor(constructionProjectRemoteApiService.getProjectAssignmentsByPersonId(personId), ProjectAssignmentResponse.class));

        return new ResponseData<PersonResponse>().success(personResponse);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<PersonResponse> getQueryPersonInfo(Long personId) {
        PersonInfoVo personInfoVo = personQueryService.getPersonInfo(personId);
        return new ResponseData<PersonResponse>().success(dozerUtil.convertor(personInfoVo, PersonResponse.class));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<PersonResponse> getQueryPersonInfoSkipToken(Long personId) {
        PersonInfoVo personInfoVo = personQueryService.getPersonInfo(personId);
        return new ResponseData<PersonResponse>().success(dozerUtil.convertor(personInfoVo, PersonResponse.class));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<Boolean> putEditPersonStatus(Long personId, boolean enable) {
        personApplicationService.editPersonStatus(personId, enable);
        return new ResponseData<Boolean>().success(true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<Boolean> deletePersonBasicAndAllAssignments(Long personId) {
        personApplicationService.deletePersonBasicAndAllAssignments(personId);
        return new ResponseData<Boolean>().success(true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @SkipSqlPermission
    public ResponseData<ScopeTopPermissionResponse> getScopeTopPermission() {
        ScopeTopPermissionResponse response = new ScopeTopPermissionResponse();
        AuthorityAccessResponse access = authorityUtil.getLoginAccess();
        List<ProjectBasicResponse> projectBasics = new ArrayList<>();

        // 判断管理员操作
        if (access.isAdmin()) {
            // 全量项目
            projectBasics = constructionProjectRemoteApiService.getQueryAllProjectBasicList();
            // 获取所有项目
            HrOrganizationResponse hrOrganization = organizationRemoteApiService.getTopHrOrganizationScopeList(new ArrayList<>(), true);
            response.setHrOrganization(dozerUtil.convertor(hrOrganization, ScopeHrOrganizationResponse.class));
        } else {
            if (access.isInternal()) {
                List<Long> hrOrganizationIds = personQueryService.getAssignmentHrOrganizationIdsByPersonId(access.getPersonId());
                HrOrganizationResponse hrOrganization = organizationRemoteApiService.getTopHrOrganizationScopeList(hrOrganizationIds, false);
                response.setHrOrganization(dozerUtil.convertor(hrOrganization, ScopeHrOrganizationResponse.class));
                // 获取当前组织下的项目
                projectBasics.addAll(constructionProjectRemoteApiService.getQueryProjectBasicListByHrOrganizationIds(hrOrganization.getHrOrganizationChildren().stream().map(HrOrganizationResponse::getHrOrganizationId).collect(Collectors.toList())));
            }

            projectBasics.addAll(constructionProjectRemoteApiService.getQueryProjectBasicListByPersonId(access.getPersonId())); // 无论内外部人员都将项目绑定
        }

        projectBasics = projectBasics.stream().distinct().collect(Collectors.toList()); // 去重

        response.setInternal(access.isInternal())
                .setProjectBasics(projectBasics.stream().map(project ->
                                new ScopeProjectBasicResponse()
                                        .setProjectId(project.getProjectId())
                                        .setProjectFullName(project.getProjectName())
                                        .setProjectShortName(project.getProjectShortName()))
                        .collect(Collectors.toList()));

        return new ResponseData<ScopeTopPermissionResponse>().success(response);
    }

    @Override
    @SkipSqlPermission
    public ResponseData<ScopeTopPermissionInfoResponse> getScopeTopPermissionInfo() {
        ScopeTopPermissionInfoResponse response = new ScopeTopPermissionInfoResponse();
        NodeInfoResponse node1 = new NodeInfoResponse();
        List<NodeInfoResponse> node2s = new ArrayList<>();
        List<Long> instituteIds = new ArrayList<>();

        List<ProjectBasicInfoResponse> allProjectBasicList = dozerUtil.convertor(constructionProjectRemoteApiService.getQueryAllProjectBasicList(), ProjectBasicInfoResponse.class);
        List<HrOrganizationInfoResponse> allHrOrganization = dozerUtil.convertor(organizationRemoteApiService.getAllHrOrganization(), HrOrganizationInfoResponse.class);

        // 获取当前人所属项目id
        Map<String, List<Long>> dataScope = authorityUtil.getDataScope();
        List<Long> projectIdScope = dataScope.getOrDefault("project", null);
        // 如果当前人权限范围没有项目则返回空
        if (null == projectIdScope) {
            return null;
        }

        // 排序
        List<HrOrganizationInfoResponse> allHrOrganizationSorted = allHrOrganization.stream().sorted(Comparator.comparing(HrOrganizationInfoResponse::getDisplayOrder)).collect(Collectors.toList());

        // 获取当前人是否为内部人员
        AuthorityAccessResponse authorityAccessResponse = authorityUtil.getLoginAccess();

        // 每个项目遍历
        allProjectBasicList.forEach(projectBasicResponse -> {
            if (projectIdScope.contains(projectBasicResponse.getProjectId())) {
                NodeInfoResponse node3 = new NodeInfoResponse();
                node3.setId(projectBasicResponse.getProjectId());
                node3.setNodeId("p" + projectBasicResponse.getProjectId().toString());
                node3.setNodeName(projectBasicResponse.getProjectName());
                node3.setType("project");
                // 如果没有组织节点 就新建
                if (!instituteIds.contains(projectBasicResponse.getHrOrganizationId())) {
                    NodeInfoResponse node2 = new NodeInfoResponse();
                    HrOrganizationInfoResponse hrOrganizationResponse = allHrOrganizationSorted.stream().filter(x -> Objects.equals(x.getHrOrganizationId(), projectBasicResponse.getHrOrganizationId())).findFirst().orElseThrow(() -> LogicException.raise(CustomError.PROJECT_NOT_AVAILABLE));
                    node2.setId(hrOrganizationResponse.getHrOrganizationId());
                    node2.setNodeId("o" + hrOrganizationResponse.getHrOrganizationId());
                    node2.setNodeName(hrOrganizationResponse.getFullName());
                    node2.setType("organization");
                    node2.getChildren().add(node3);
                    node2s.add(node2);
                    instituteIds.add(projectBasicResponse.getHrOrganizationId());
                } else {
                    NodeInfoResponse node2 = node2s.stream().filter(x -> Objects.equals(x.getId(), projectBasicResponse.getHrOrganizationId())).findFirst().orElseThrow(() -> LogicException.raise(CustomError.PROJECT_NOT_AVAILABLE));
                    node2.getChildren().add(node3);
                }
            }
        });

        // 获取根节点
        HrOrganizationInfoResponse hrOrganizationResponseRoot = allHrOrganization.stream().filter(HrOrganizationInfoResponse::isRoot).findFirst().orElseThrow(() -> LogicException.raise(CustomError.PROJECT_NOT_AVAILABLE));
        node1.setId(hrOrganizationResponseRoot.getHrOrganizationId());
        node1.setNodeId("c" + hrOrganizationResponseRoot.getHrOrganizationId().toString());
        node1.setNodeName(hrOrganizationResponseRoot.getFullName());
        node1.setType("organization");
        node1.setChildren(node2s);

        response.setInternal(authorityAccessResponse.isInternal());
        response.setNode1(node1);

        return new ResponseData<>().success(response);
    }

    /**
     * 根据项目id获取项目组织id
     *
     * @param projectIds
     * @return
     */
    private List<Long> getProjectOrganizationIdsByProjectId(List<Long> projectIds) {
        if (projectIds != null) {
            List<Long> list = new ArrayList<>();
            for (Long id : projectIds) {
                list.addAll(organizationRemoteApiService.getAllProjectOrganizationsByProjectId(id)
                        .stream().map(ProjectOrganizationResponse::getProjectOrganizationId)
                        .collect(Collectors.toList())
                );
            }
            list = list.stream().distinct().collect(Collectors.toList());
            if (list.size() > 0) {
                return list;
            }
        }
        return null;
    }

    /**
     * 根据项目id获取所属项目管理组织及下级组织
     *
     * @param projectId
     * @param internal
     * @return
     */
    private List<Long> getHrOrganizationIdsByProjectId(Long projectId, boolean internal) {
        if (internal) {
            List<Long> hrOrganizationIds = new ArrayList<>();
            ProjectBasicResponse project = constructionProjectRemoteApiService.getProjectBasicByProjectId(projectId);
            // 获取项目组织及根节点
            hrOrganizationIds.addAll(organizationRemoteApiService.getParentHrOrganizationIdsByHrOrganizationId(project.getHrOrganizationId()));

            // 获取该企业组织下节点及其本身
            hrOrganizationIds.addAll(organizationRemoteApiService.getHrOrganizationChildrenOrgIdList(project.getHrOrganizationId()));

            return hrOrganizationIds.stream().distinct().collect(Collectors.toList());
        } else {
            return new ArrayList<>();
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @SkipSqlPermission
    public ResponseData<ScopeTopPermissionResponse> getLoginScopeInitializeDataAndSubmit() {

        String token = authorityUtil.getAccessToken();

        ResponseData<ScopeTopPermissionResponse> response = getScopeTopPermission();

        if (response.isSuccess()) {
            boolean internal = response.getData().isInternal();

            // 企业内部需要重置符合权限的企业组织id
            List<Long> hrOrganizationIds = new ArrayList<>();
            if (internal) {
                List<Long> children = response.getData().getHrOrganization().getHrOrganizationChildren().stream().map(ScopeHrOrganizationResponse::getHrOrganizationId).collect(Collectors.toList());
                hrOrganizationIds.addAll(fetchTopDataScopeInitialize(response.getData().getHrOrganization().getHrOrganizationId(), children));

                // 判断当前用户是否属于公司、公司领导、公司管理组织，如果是的话则需要把完整组织都抛出。
                List<Long> assignmentHrOrganizationIds = authorityUtil.getLoginAccess().getInternalAssignments().stream().map(InternalAssignmentInfoResponse::getHrOrganizationId).collect(Collectors.toList());
                // 需要调用Organization的服务判断
                hrOrganizationIds.addAll(organizationRemoteApiService.getAllHrOrganizationIdsWhenYouAreInCompanyLevel(assignmentHrOrganizationIds));
            }

            // 由于不涉及到前后端交互，故不需要重新抓取一次项目id，直接获取即可
            List<ScopeProjectBasicResponse> projects = response.getData().getProjectBasics();
            List<Long> projectIds = (projects.size() > 0) ? projects.stream().map(ScopeProjectBasicResponse::getProjectId).collect(Collectors.toList()) : null;

            if (projects.size() > 0) {
                AuthorityAccessResponse access = authorityUtil.getLoginAccess();
                for (Long projectId : projectIds) {
                    hrOrganizationIds.addAll(getHrOrganizationIdsByProjectId(projectId, true));
                }

                // 外部人员需要把上级组织均带出来
                if (!access.isInternal()) {
                    List<Long> parents = new ArrayList<>();
                    hrOrganizationIds.stream().forEach(hrOrganizationId -> {
                        parents.addAll(organizationRemoteApiService.getParentHrOrganizationIdsByHrOrganizationId(hrOrganizationId));
                    });

                    hrOrganizationIds.addAll(parents.stream().distinct().collect(Collectors.toList()));
                }
            }

            // 除重
            hrOrganizationIds = hrOrganizationIds.stream().distinct().collect(Collectors.toList());

            // 获取项目下的项目组织
            List<Long> projectOrganizationIds = getProjectOrganizationIdsByProjectId(projectIds);

           /* //去除下属部门的组织Id
            for (Long hrOrganizationId : hrOrganizationIds) {
                HrOrganizationResponse hrOrganizationResponse = organizationRemoteApiService.getHrOrganizationView(hrOrganizationId);
                if (hrOrganizationResponse.getType() == "SUBORDINATE_ORGANIZATION") {
                    hrOrganizationIds.remove(hrOrganizationId);
                    log.info("删除成功");
                }
            }*/

            Map<String, List<Long>> maps = new HashMap<>();
            maps.put(SqlItemEnum.hrOrganization.getValue(), hrOrganizationIds);
            maps.put(SqlItemEnum.project.getValue(), projectIds);
            maps.put(SqlItemEnum.projectOrganization.getValue(), projectOrganizationIds);

            DataPermissionScopeRequest dataPermissionScopeRequest = new DataPermissionScopeRequest()
                    .setToken(token)
                    .setDataScope(maps);

            authorityAccessRemoteApiService.boundDataPermissionScope(dataPermissionScopeRequest);
        }
        return response;
    }

    /**
     * 获取初始化时候得到的组织id数组
     *
     * @param rootHrOrganizationId
     * @param hrOrganizationIds
     * @return
     */
    private List<Long> fetchTopDataScopeInitialize(Long rootHrOrganizationId, List<Long> hrOrganizationIds) {
        List<Long> list = new ArrayList<Long>() {{
            add(rootHrOrganizationId);
        }};
        for (Long hrOrganizationId : hrOrganizationIds) {
            list.addAll(organizationRemoteApiService.getHrOrganizationChildrenOrgIdList(hrOrganizationId));
        }
        return list.stream().distinct().collect(Collectors.toList());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @SkipSqlPermission
    public ResponseData<Boolean> postSubmitScopeTopPermission(ScopeTopPermissionRequest scopeTopPermissionRequest) {
        String token = authorityUtil.getAccessToken();
        if (StringUtils.isEmpty(token)) {
            throw LogicException.raise(BasicError.TOKEN_MISS);
        }

        Long projectId = scopeTopPermissionRequest.getProjectId();
        Long hrOrganizationId = scopeTopPermissionRequest.getHrOrganizationId();
        List<Long> hrOrganizationIds = new ArrayList<>();
        List<Long> projectOrganizationIds;
        List<Long> projectIds = null;

        if (hrOrganizationId != null) {
            // 获取该企业组织下节点及其本身
            hrOrganizationIds = organizationRemoteApiService.getHrOrganizationChildrenOrgIdList(hrOrganizationId);
            // 获取该企业组织下所有项目
            List<ProjectBasicResponse> projectBasics = constructionProjectRemoteApiService.getQueryProjectBasicListByHrOrganizationIds(hrOrganizationIds);
            projectIds = projectBasics.stream().map(ProjectBasicResponse::getProjectId).collect(Collectors.toList());

        } else {
            if (projectId != null) {
                projectIds = new ArrayList<Long>() {{
                    add(projectId);
                }};
                AuthorityAccessResponse access = authorityUtil.getLoginAccess();
                hrOrganizationIds.addAll(getHrOrganizationIdsByProjectId(projectId, true)); // 根据项目id获取所属项目管理组织及下级组织

                // 外部人员需要把上级组织均带出来
                if (!access.isInternal()) {
                    List<Long> parents = new ArrayList<>();
                    hrOrganizationIds.forEach(id -> parents.addAll(organizationRemoteApiService.getParentHrOrganizationIdsByHrOrganizationId(id)));

                    hrOrganizationIds.addAll(parents.stream().distinct().collect(Collectors.toList()));
                }
            }
        }

        // 无论什么情况都拼接一个root，防止展现树结构时找不到根报错。
        HrOrganizationResponse root = organizationRemoteApiService.getHrOrganizationRoot();
        if (!hrOrganizationIds.contains(root.getHrOrganizationId())) {
            hrOrganizationIds.add(root.getHrOrganizationId());
        }

        // 获取项目下的项目组织
        projectOrganizationIds = getProjectOrganizationIdsByProjectId(projectIds);

        // 去重
        if (projectIds != null) {
            projectIds = projectIds.stream().distinct().collect(Collectors.toList()); // 去重
        }

        Map<String, List<Long>> maps = new HashMap<>();
        maps.put(SqlItemEnum.hrOrganization.getValue(), hrOrganizationIds);
        maps.put(SqlItemEnum.project.getValue(), projectIds);
        maps.put(SqlItemEnum.projectOrganization.getValue(), projectOrganizationIds);

        DataPermissionScopeRequest dataPermissionScopeRequest = new DataPermissionScopeRequest()
                .setToken(token)
                .setDataScope(maps);

        authorityAccessRemoteApiService.boundDataPermissionScope(dataPermissionScopeRequest);

        return new ResponseData<Boolean>().success(true);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public ResponseData<List<PersonSimpleResponse>> getQueryPersonSimpleByCurrentHrOrganizationId(Long hrOrganizationId) {
        return new ResponseData<List<PersonSimpleResponse>>().success(dozerUtil.convertor(personQueryService.getPersonsByCurrentHrOrganizationId(hrOrganizationId), PersonSimpleResponse.class));
    }

    @Override
    public ResponseData<List<PersonResponse>> getPersonInProjectWithRoleIds(Long projectId, List<Long> roleIds) {

        List<Long> personIdsWithRoleIds = authorityAccessRemoteApiService.getQueryAllPersonIdsByRoleId(roleIds);

        // 保留原顺序去重
        LinkedHashSet<Long> temp = new LinkedHashSet<>(personIdsWithRoleIds);
        personIdsWithRoleIds.clear();
        personIdsWithRoleIds.addAll(temp);

        List<Long> personIdsByProjectId = constructionProjectRemoteApiService.getQueryPersonIdsByProjectId(projectId);

        // 保留角色顺序取交集
        personIdsWithRoleIds.retainAll(personIdsByProjectId);
        List<PersonInfoVo> personInfoByPersonIds = personQueryService.getPersonInfoByPersonIds(personIdsWithRoleIds);

        return new ResponseData<>().success(dozerUtil.convertor(personInfoByPersonIds, PersonResponse.class));

    }

    @Override
    public ResponseData<List<PersonResponse>> getPersonInProject(Long projectId) {
        List<Long> personIdsByProjectId = constructionProjectRemoteApiService.getQueryPersonIdsByProjectId(projectId);
        List<PersonInfoVo> personInfoByPersonIds = personQueryService.getPersonInfoByPersonIds(personIdsByProjectId);

        return new ResponseData<>().success(dozerUtil.convertor(personInfoByPersonIds, PersonResponse.class));
    }

    @Override
    public ResponseData<List<PersonResponse>> getPersonInOrganizationWithRoleIds(Long organizationId, List<Long> roleIds) {

            List<Long> personIdsWithRoleIds = authorityAccessRemoteApiService.getQueryAllPersonIdsByRoleId(roleIds);

            // 保留原顺序去重
            LinkedHashSet<Long> temp = new LinkedHashSet<>(personIdsWithRoleIds);
            personIdsWithRoleIds.clear();
            personIdsWithRoleIds.addAll(temp);

            List<Long> personIdsByOrganizationId = personQueryService.getPersonIdsByOrganizationId(organizationId);

            personIdsWithRoleIds.retainAll(personIdsByOrganizationId);
            List<PersonInfoVo> personInfoByPersonIds = personQueryService.getPersonInfoByPersonIds(personIdsWithRoleIds);

            return new ResponseData<>().success(dozerUtil.convertor(personInfoByPersonIds, PersonResponse.class));

    }

    @Override
    public ResponseData<List<Long>> getOrganizationIdWithPersonId(Long personId) {
        List<Long> organizationIds = personQueryService.getAssignmentHrOrganizationIdsByPersonId(personId);
        return new ResponseData<>().success(organizationIds);
    }

    @Override
    public ResponseData<List<InternalAssignmentResponse>> getInternalAssignmentWithPersonId(Long personId) {
        List<Assignment> internalAssignmentByPersonId = personQueryService.getInternalAssignmentByPersonId(personId);
        return new ResponseData<>().success(dozerUtil.convertor(internalAssignmentByPersonId, InternalAssignmentResponse.class));
    }

    @Override
    public ResponseData<List<PersonSimpleResponse>> getQueryPersons(List<Long> personIds) {
        List<Person> peopleByPersonIds = personQueryService.getPeopleByPersonIds(personIds);
        return new ResponseData<>().success(dozerUtil.convertor(peopleByPersonIds, PersonSimpleResponse.class));
    }

    @Override
    public ResponseData<Boolean> postBatchAddExistingPerson(BatchExistingPersonRequest batchExistingPersonRequest) {
        boolean flag = personApplicationService.postBatchAddExistingPerson(batchExistingPersonRequest.getPersonIds(), batchExistingPersonRequest.getHrOrganizationId());
        return new ResponseData<Boolean>().success(flag);
    }

    @Override
    public ResponseData<List<PersonResp>> getPersonList(PersonListQueryRequest personListQueryRequest) {
        PersonListQueryCommand personListQueryCommand = adapterConverter.personListQueryRequestToPersonListQueryCommand(personListQueryRequest);
        List<SimplePerson> people = personQueryService.getSimplePersonList(personListQueryCommand);
        List<PersonResp> personResps = adapterConverter.peopleToPersonResp(people);
        return new ResponseData<Boolean>().success(personResps);
    }

    @Override
    public ResponseData<List<PersonDetailResp>> getPersonDetailList(PersonListQueryRequest personListQueryRequest) {
        PersonListQueryCommand personListQueryCommand = adapterConverter.personListQueryRequestToPersonListQueryCommand(personListQueryRequest);
        List<PersonDetailVo> personDetailVos = personQueryService.getPersonDetailList(personListQueryCommand);
        List<PersonDetailResp> personDetailResps = adapterConverter.personDetailVoToPersonDetailResp(personDetailVos);
        return new ResponseData<Boolean>().success(personDetailResps);
    }

    @Override
    public ResponseData<List<PersonResp>> getPersonListWithoutToken(PersonListQueryRequest personListQueryRequest) {
        PersonListQueryCommand personListQueryCommand = adapterConverter.personListQueryRequestToPersonListQueryCommand(personListQueryRequest);
        List<SimplePerson> people = personQueryService.getSimplePersonList(personListQueryCommand);
        List<PersonResp> personResps = adapterConverter.peopleToPersonResp(people);
        return new ResponseData<Boolean>().success(personResps);
    }

    @Override
    public ResponseData<List<OrganizationAssignmentResp>> getOrganizationAssignmentList(OrganizationAssignmentListQueryRequest organizationAssignmentListQueryRequest) {
        OrganizationAssignmentListQueryCommand organizationAssignmentListQueryCommand = adapterConverter.organizationAssignmentListQueryRequestToOrganizationListQueryCommand(organizationAssignmentListQueryRequest);
        List<OrganizationAssignment> organizationAssignments = personQueryService.getOrganizationAssignmentList(organizationAssignmentListQueryCommand);
        List<OrganizationAssignmentResp> organizationAssignmentResps = adapterConverter.organizationAssignmentToOrganizationAssignmentResp(organizationAssignments);
        return new ResponseData<Boolean>().success(organizationAssignmentResps);
    }

    @Override
    public ResponseData<List<OrganizationAssignmentResp>> getOrganizationAssignmentListWithoutToken(OrganizationAssignmentListQueryRequest organizationAssignmentListQueryRequest) {
        OrganizationAssignmentListQueryCommand organizationAssignmentListQueryCommand = adapterConverter.organizationAssignmentListQueryRequestToOrganizationListQueryCommand(organizationAssignmentListQueryRequest);
        List<OrganizationAssignment> organizationAssignments = personQueryService.getOrganizationAssignmentList(organizationAssignmentListQueryCommand);
        List<OrganizationAssignmentResp> organizationAssignmentResps = adapterConverter.organizationAssignmentToOrganizationAssignmentResp(organizationAssignments);
        return new ResponseData<Boolean>().success(organizationAssignmentResps);
    }
}
